package com.it.cloud.generator.result;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.it.cloud.common.R;
import com.it.cloud.common.vo.TreeNode;
import com.it.cloud.common.vo.TreeNodeTitleSlot;
import com.it.cloud.dao.BaseDao;
import ${entityImport};
import cn.hutool.core.util.StrUtil;
import lombok.AllArgsConstructor;

@Service
@AllArgsConstructor
public class ${name}ServiceImpl implements ${name}Service {
	
	private BaseDao baseDao;
	
	public TreeNodeTitleSlot genTitleSlot() {
		TreeNodeTitleSlot slot = new TreeNodeTitleSlot();
		slot.setTitle("titleWithBtn");
		return slot;
	}

	public TreeNode genTreeNode(${name} obj) {
		TreeNode node = new TreeNode();
		node.setTitle(obj.getName());
		node.setKey(String.valueOf(obj.getId()));
		node.setScopedSlots(genTitleSlot());
		List<TreeNode> children = new ArrayList<>();
		node.setChildren(children);
		return node;
	}
	
	@Override
	public List<TreeNode> genTreeNodeList(List<${name}> list) {
		return list.stream().map(t->genTreeNode(t)).collect(Collectors.toList());
	}
	
	@Override
	public List<${name}> findChild(Long pid) {
		List<${name}> list = baseDao.find(${name}.class, 
			${name}.PID+"=?0", new Object[] {pid} , ${name}.SORT);
		return list;
	}

	@Override
	public Boolean hasChild(Long pid) {
		return baseDao.exist(${name}.class, ${name}.PID+"=?0", new Object[] {pid});
	}

	@Override
	public String generateName(Long pid) {
		String defaultName = "新节点";
		String name = defaultName;
		int i = 1;
		while(baseDao.exist(${name}.class, ${name}.NAME+"=?0 and "+${name}.PID+"=?1", new Object[] {name, pid})) {
			name = defaultName+"("+i+")";
			i++;
		}
		return name;
	}
	
	@Override
	public Boolean isNameExist(Long id, String name) {
		${name} obj = baseDao.findById(${name}.class, id);
		return baseDao.exist(${name}.class, 
				${name}.NAME+"=?0 and "+${name}.PID+"=?1 and "+${name}.ID+"!=?2", new Object[] {name, obj.getPid(), id});
	}
	
	@Override
	public Boolean isCodeExist(Long id, String code) {
		return StrUtil.isNotEmpty(code) && baseDao.exist(${name}.class, ${name}.CODE+"=?0 and "+${name}.ID+"!=?1", new Object[] {code, id});
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public void moveInner(${name} dragObj, ${name} dropObj) {
		Long pid = dropObj.getId();
		if(!dragObj.getPid().equals(pid)) {
			//之前不是子节点
			dragObj.setPid(pid);
			dragObj.setLayer(dropObj.getLayer()+1);
		}
		//放到所有子节点的后面
		dragObj.setSort(findMaxSort(dropObj.getId())+1);
		baseDao.update(dragObj);
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public void moveBefore(${name} dragObj, ${name} dropObj) {
		Long pid = dropObj.getPid();
		Integer sort = dropObj.getSort();
		String jpql = " update "+${name}.class.getName()+" set "+${name}.SORT+" = "+${name}.SORT+"+1 where "+
				${name}.SORT+">=?0 and "+${name}.PID+"=?1";
		baseDao.execute(jpql, new Object[] {sort, pid});
		dragObj.setPid(pid);
		${name} parent = baseDao.findById(${name}.class, pid);
		dragObj.setLayer(parent==null?1:(parent.getLayer()+1));
		dragObj.setSort(sort);
		baseDao.update(dragObj);
	}

	@Override
	@Transactional(rollbackFor=Exception.class)
	public void moveAfter(${name} dragObj, ${name} dropObj) {
		Long pid = dropObj.getPid();
		Integer sort = dropObj.getSort();
		String jpql = " update "+${name}.class.getName()+" set "+${name}.SORT+" = "+${name}.SORT+"+1 where "+
				${name}.SORT+">?0 and "+${name}.PID+"=?1";
		baseDao.execute(jpql, new Object[] {sort,pid});
		${name} parent = baseDao.findById(${name}.class, pid);
		dragObj.setPid(pid);
		dragObj.setLayer(parent==null?1:(parent.getLayer()+1));
		dragObj.setSort(sort+1);
		baseDao.update(dragObj);
	}
	
	@Override
	public int findMaxSort(Long pid) {
		return baseDao.findInt(" max("+${name}.SORT+") ", 
			${name}.class, ${name}.PID+"=?0", new Object[] {pid});
	}
	
	@Override
	@Transactional(rollbackFor=Exception.class)
	public String[] generateNamesAndIds(Long id) {
		${name} obj = baseDao.findById(${name}.class, id);
		StringBuffer idSb = new StringBuffer();
		StringBuffer nameSb = new StringBuffer();
		idSb.append(obj.getId()+",");
		nameSb.append(obj.getName()+"/");
		Long pid = obj.getPid();
		while(pid!=null) {
			${name} at = baseDao.findById(${name}.class, pid);
			idSb.append(at.getId()+",");
			nameSb.append(at.getName()+"/");
			pid = at.getPid();
		}
		return new String[] {
			nameSb.substring(0,nameSb.length()-1),
			idSb.substring(0,idSb.length()-1)};
	}
	
	@Override
	@Transactional(rollbackFor=Exception.class)
	public R<TreeNode> addChild(Long pid) {
		${name} obj = new ${name}();
		obj.setPid(pid);
		obj.setName(generateName(pid));
		obj.setCode("");
		${name} parent = baseDao.findById(${name}.class, pid);
		obj.setLayer(parent==null?1:(parent.getLayer()+1));
		obj.setSort(findMaxSort(pid)+1);
		baseDao.save(obj);
		return R.success(genTreeNode(obj));
	}
}
